package com.banquetmanagementsystem.common.Utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.banquetmanagementsystem.common.context.BaseContext;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;

/**
 * token工具类
 *
 * @author tanghaihua
 */
@Component
public class TokenUtil {
    @Resource
    private TokenUtilProperties tokenUtilProperties;
    private static final long FIVE_MINUTES = 1000 * 60 * 5;
    private static final long TWELVE_HOURS = 12 * 60 * 60 * 1000;
    private static final long WEEK_DAYS = 1000 * 60 * 60 * 24 * 7;

    /**
     * 签名生成
     *
     * @param claims 需要签名的数据
     * @param time   过期时间
     * @param secret 密钥盐
     * @return 返回生成的token
     */
    public <V> String sign(Map<String, V> claims, long time, String secret) {
        String token = null;
        try {
            Date expiresAt = new Date(System.currentTimeMillis() + time);
            token = JWT.create()
                    .withExpiresAt(expiresAt)
                    .withPayload(claims)
                    .sign(Algorithm.HMAC256(secret));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return token;
    }

    /**
     * 获取一个长时间有效的token
     *
     * @param claims                  需要签名的数据
     * @param isWeeklyDurationEnabled 是否开启一周有效期
     * @return 返回生成的token
     */
    public <V> String getRefreshToken(Map<String, V> claims, boolean isWeeklyDurationEnabled) {
        String refreshTokenSecret = tokenUtilProperties.getRefreshTokenSecret();
        if (isWeeklyDurationEnabled) {
            return sign(claims, WEEK_DAYS, refreshTokenSecret);
        } else {
            return sign(claims, TWELVE_HOURS, refreshTokenSecret);
        }
    }

    /**
     * 获取一个短时间时间有效的token
     *
     * @param claims 需要签名的数据
     * @return 返回生成的token
     */
    public <V> String getAccessToken(Map<String, V> claims) {
        String accessTokenSecret = tokenUtilProperties.getAccessTokenSecret();
        return sign(claims, FIVE_MINUTES, accessTokenSecret);
    }

    /**
     * 签名验证
     */
    public boolean verify(String token,String secret) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
            DecodedJWT jwt = verifier.verify(token);
            Integer userId = Integer.valueOf(jwt.getClaim("userId").asString());
            String username = jwt.getClaim("username").asString();
            Boolean isWeeklyDurationEnabled = Boolean.valueOf(jwt.getClaim("isWeeklyDurationEnabled").asString());
            System.err.println("认证通过：");
            System.err.println("过期时间：" + jwt.getExpiresAt());
            BaseContext.setThreadLocalId(userId);
            BaseContext.setThreadLocalName(username);
            BaseContext.setThreadLocalIsWeeklyDurationEnabled(isWeeklyDurationEnabled);
            return true;
        } catch (Exception e) {
            System.err.println("认证失败：" + e.getMessage());
            return false;
        }
    }

    /**
     * 验证长期有效token
     * @param token 需要验证的token
     * @return 是否验证通过
     */
    public boolean verifyRefreshToken(String token){
        return verify(token,tokenUtilProperties.getRefreshTokenSecret());
    }
    /**
     * 验证短期有效token
     * @param token 需要验证的token
     * @return 是否验证通过
     */
    public boolean verifyAccessToken(String token){
        return verify(token,tokenUtilProperties.getAccessTokenSecret());
    }
}
